package top.hekun.study.core;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import top.hekun.study.core.util.ClassFileUtil;
import top.hekun.study.core.visitor.method.simple.*;

import java.io.File;
import java.util.Arrays;

/**
 * 〈类修改方法代码演示〉
 *  类简单修改方法代码
 *
 * @author: Sakura
 * @date: 2023/5/10
 */
public class ClassSimpleModifyMethodCodeDemo {
    public static void main(String[] args) {
        byte[] classBytes = ClassFileUtil.getClassFileByteToClassName("HelloWordModifyMethodCode");
        ClassReader classReader = new ClassReader(classBytes);
        System.out.println("access > " + classReader.getAccess());
        System.out.println("className > " + classReader.getClassName());
        System.out.println("classSuperName > " + classReader.getSuperName());
        System.out.println("Interfaces > " + Arrays.toString(classReader.getInterfaces()));
        System.out.println();


        // 类编写器
        ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        int apiVersion = Opcodes.ASM9;
        ClassVisitor classVisitor0 = new MyClassVisitorModifyMethodCode0(apiVersion, classWriter);
        // 更改方法 进入添加代码
        ClassVisitor classVisitor1 = new MyClassVisitorModifyMethodCode1(apiVersion, classVisitor0);
        // 更改方法 退出添加代码
        ClassVisitor classVisitor2 = new MyClassVisitorModifyMethodCode2(apiVersion, classVisitor1);
        // 更改方法  进入 和 退出添加代码 2种方法
        ClassVisitor classVisitor3 = new MyClassVisitorModifyMethodCode3(apiVersion, classVisitor2);
        // 打印参数和 方法返回值
        ClassVisitor classVisitor4 = new MyClassVisitorModifyMethodCode4(apiVersion, classVisitor3);
        // 打印方法参数和返回值 方法
        ClassVisitor classVisitor5 = new MyClassVisitorModifyMethodCode5(apiVersion, classVisitor4);
        // 打印方法执行时间
        ClassVisitor classVisitor6 = new MyClassVisitorModifyMethodCode6(apiVersion, classVisitor5);
        //   打印方法参数和返回值 AdviceAdapter
        ClassVisitor classVisitor7 = new MyClassVisitorModifyMethodCode7(apiVersion, classVisitor6);

        // 运行的时候 方法倒序调用 6>5>4>3>2>1
        classReader.accept(classVisitor7, ClassReader.EXPAND_FRAMES | ClassReader.SKIP_DEBUG);
        byte[] classByte = classWriter.toByteArray();
        writeClassFileCore(classByte, getClassFile());
    }

    private static File getClassFile() {
        String className = "HelloWordModifyMethodCodeModifyClass";
        File file = new File(ClassFileUtil.getClassFileModelPath(), className + ".class");
        return file;
    }

    private static void writeClassFileCore(byte[] core, File classFilePath) {
        ClassFileUtil.classFileCoreWrite(core, classFilePath);
    }

}
